﻿
namespace Octopus.VMDeployer

open System.Xml.Linq

(*
type ActionType =
  | Unknown = 0
  | JoinDomain = 1
  | UnjoinDomain = 2
  | InstallMsi = 3
  | InstallExe = 4
*)



[<AbstractClass>]
type BaseConfigurationData (vmGuid:System.Guid, machineName:string, ownerName:string, adminPassword:string, securityToken:System.Guid, octopusServiceAddresses:string array) =
  let mutable deployingState = (-1,0)
  let mutable rebootAction = fun() -> ()
  
  member internal x.DeployingState
    with get() = deployingState
    and set(v) = deployingState <- v

  member internal x.RebootAction with set(v) = rebootAction <- v
  
  member x.VmGuid = vmGuid
  member x.MachineName = machineName
  member x.OwnerName = ownerName
  member x.AdminPassword = adminPassword
  member x.SecurityToken = securityToken
  member x.OctopusServiceAddresses = octopusServiceAddresses
  
  member x.IsFinished = match deployingState with (-3,_) -> true | _ -> false
  member x.Reboot() = rebootAction()

  abstract ExecuteDeploy : System.IO.TextWriter -> unit





[<AbstractClass>]
type Action () =
  abstract ExecuteAction : BaseConfigurationData -> int -> int * (unit -> unit)
  abstract ToXmlElement : unit -> System.Xml.Linq.XElement





type DeployHpcNode (scheduler:string, domainName:string, adminAccount:string*string) =
  inherit Action()
  
  member private x.Step1 (conf:BaseConfigurationData) =
    // main action already changed account psw and computer name
    Functions.joinDomain domainName adminAccount
    (1, (fun () -> try Functions.win32Shutdown Functions.Win32ShutdownFlags.Reboot
                   with _ -> Functions.win32Shutdown Functions.Win32ShutdownFlags.RebootForced))
    
  member private x.Step2 (conf:BaseConfigurationData) =
    Functions.octopus_notifyHpcNodeReady conf.VmGuid conf.SecurityToken conf.OctopusServiceAddresses
    (0,id)
  
  override x.ExecuteAction baseConf currentState =
    match currentState with
    | 0 -> x.Step1 baseConf
    | 1 -> x.Step2 baseConf
    | n -> failwithf "Invalid state: %d" n
    

  // -----------------------------------------------------------

  override x.ToXmlElement () =
    let u,p = adminAccount
    let data = [| new XElement(XName.op_Implicit "Scheduler", scheduler);
                  new XElement(XName.op_Implicit "DomainName", domainName);
                  new XElement(XName.op_Implicit "DomainAdminUsername", u);
                  new XElement(XName.op_Implicit "DomainAdminPassword", p) |]
    let p = new XElement(XName.op_Implicit "Action", data)
    p.SetAttributeValue(XName.op_Implicit "Name", "DeployHpcNode")
    p
  
  static member FromXmlNode (node:System.Xml.Linq.XElement) =
    let scheduler = node.Element(XName.op_Implicit "Scheduler").Value
    let domainName = node.Element(XName.op_Implicit "DomainName").Value
    let user = node.Element(XName.op_Implicit "DomainAdminUsername").Value
    let pass = node.Element(XName.op_Implicit "DomainAdminPassword").Value
    new DeployHpcNode(scheduler, domainName, (user,pass))

